/*
 * Controler for map
 */

package game.scene.map;
import game.scene.BaseScene;
import dgo.interval.*;
import dgo.MyLib;
import java.util.Vector;
import java.util.Enumeration;
import dgo.tilemap.*;
import game.scene.map.event.*;
import dgo.SimpleInput;
import game.scene.SceneStack;

/**
 *
 * @author Daigo
 */
public class Controller {

  
  /* -------------------------
  caliculate and set target character center of the map.
   (if target character is near the edge of the map, the map won't scroll)
   --------------------------*/ 
  public void updateBase(Model model){
    int x = model.player().screenX;
    int y = model.player().screenY;
    int tx = x - model.map.gridWidth * ((model.showWidth / 2) / model.map.gridWidth);
    int ty = y - model.map.gridHeight * ((model.showHeight / 2) / model.map.gridHeight);
    if(tx < 0) tx = 0;
    if(ty < 0) ty = 0;
    
    if(tx >= model.map.width() - model.showWidth){
      tx = model.map.width() - model.showWidth;
    }
    if(ty >= model.map.height() - model.showHeight){
      ty = model.map.height() - model.showHeight;
    }
    
    model.map.baseX = tx;
    model.map.baseY = ty;
  }
  
  private void checkObject(Model model, MapCharacter character, int tx, int ty){
    MapCharacter mc = model.map.getCharacter(tx, ty);
    if(mc != null && mc != character){ mc.check(character); }
  }
  
  private void resetClockSwitches(Model model){
    for(int i = 21; i <= 23; i++){
      model.globalModel.switches[i] = false;
    }
  }

  private void clockToggle(Model model){
    if(SimpleInput.isPressedNewly("cancel")){
      model.player().pause = true;
      model.globalModel.variables[12] = 1;
      // Play SE
      MyLib.playSE(getClass(), "cloth");
      model.getEvent(0).setCharacterChip(model, "Ghost", 4, 1);
    }
  }
      
  public void clockControl(Model model){
    
    if(model.player().isRunning()){return;}
    
    if(model.player().pause){
      int var = model.globalModel.variables[12];
      if(var >= 0){
        if(SimpleInput.isPressedNewly("cancel")){
          resetClockSwitches(model);
          model.globalModel.switches[21 + var] = true;
          // play se
          MyLib.playSE(getClass(), "switch");
          if(var == 1){
            model.getEvent(0).setCharacterChip(model, "Ghost", 1, 1);
            model.player().pause = false;
          }
          var = -1;
        }else{
          int t = var;
          
          if(SimpleInput.isPressedNewly("left")){var -= 1;}
          if(SimpleInput.isPressedNewly("right")){var += 1;}
          int s = 0;
          int e = 2;
          if(model.globalModel.switches[1]){s = 1;}
          if(model.globalModel.switches[2]){e = 1;}
          var = Math.min(Math.max(var, s), e);
          
          if(t != var){
            //Play se
            MyLib.playSE(getClass(), "switch");
          }
        }
      }
      model.globalModel.variables[12] = var;
    }else{
      clockToggle(model);
    }
    
  }
  
  public void updateTasks(Model model){
    Enumeration e = model.tasks.elements();
    while(e.hasMoreElements()){
      IntervalRunner runner = (IntervalRunner)e.nextElement();
      if(!runner.isDone()){ runner.update(); }
      if(runner.isDone()){ model.tasks.removeElement(runner); }
    }
  }

  // reset collision information and characters
  public void reset(Model model){
    model.map.resetObjectCollisions();
    model.map.resetCharacters();

    Enumeration e = model.characters.elements();
    while(e.hasMoreElements()){
      MapCharacter c = (MapCharacter)e.nextElement();
      c.reset();
      // take care collisions of objects which occupies more than one grid
      for(int i=0; i < c.hitX; i++){
        for(int j=0; j < c.hitY; j++){
          model.map.setCharacter(c.mapX + i, c.mapY - j, c);
          model.map.setObjectCollision(c.mapX + i, c.mapY - j, CollisionType.ALL);
        }
      }
    }
    
  }

  public void updatePlayer(Model model){
    if(model.player().pause){return;}
    MapCharacter player = model.player();
    if(!player.isRunning() && SimpleInput.isPressedNewly("ok")){
      this.checkObject(model, player, player.mapX, player.mapY);
      this.checkObject(model, player, player.mapX + player.dirX, player.mapY + player.dirY);
    }
  }
  
  public void updateCharacters(Model model){
    // Update All character
    Enumeration e = model.characters.elements();
    while(e.hasMoreElements()){
      MapCharacter t = (MapCharacter)(e.nextElement());
      t.update();
    }
  }
  
  public void updatePlayerInput(Model model){
    Vector keys = new Vector();
    if(SimpleInput.isPressed("up")){keys.addElement("up");}
    if(SimpleInput.isPressed("down")){keys.addElement("down");}
    if(SimpleInput.isPressed("right")){keys.addElement("right");}
    if(SimpleInput.isPressed("left")){keys.addElement("left");}

    // Input Players
    model.player().inputKeys(keys);
  }

  public void updateEvents(Model model, SceneStack stack){
    Enumeration e;
    e = model.events.elements();
    while(e.hasMoreElements()){
      ((Event)(e.nextElement())).updateMovement();
    }

    e = model.events.elements();
    while(e.hasMoreElements()){
      ((Event)(e.nextElement())).update(stack);
    }
  }
  
  public void update(Model model, SceneStack stack, BaseScene scene){
          
    updateTasks(model);
    reset(model);
    clockControl(model);
    updatePlayer(model);
    updateCharacters(model);
    updateEvents(model, stack);
    updatePlayerInput(model);
    updateBase(model);
    model.map.update();
    model.windowManager.update(model.map.baseX, model.map.baseY);
  }

}
